﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WordRacer.Domain.Model.Dictionaries;
using WordRacer.Domain.Model.Boards;
using WordRacer.Domain.Model.GameCells;

    /// <summary>
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- + 
    /// |  A  |  B  |  R  |  A  |  S  |  I  |    |  1  |  2  |  3  |  4  |  5  |  6  |      
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- +           
    /// |  G  |  H  |  T  |  R  |  V  |  E  |    |  7  |  8  |  9  |  10 |  11 |  12 | 
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- + 
    /// |  E  |  I  |           |  N  |  E  |    |  13 |  14 |           |  15 |  16 | 
    /// + --- + --- +           + --- + --- +    + --- + --- +           + --- + --- + 
    /// |  T  |  T  |           |  S  |  S  |    |  17 |  18 |           |  19 |  20 | 
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- + 
    /// |  R  |  M  |  N  |  E  |  E  |  S  |    |  21 |  22 |  23 |  24 |  25 |  26 | 
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- + 
    /// |  T  |  V  |  G  |  P  |  D  |  I  |    |  27 |  28 |  29 |  30 |  31 |  32 | 
    /// + --- + --- + --- + --- + --- + --- +    + --- + --- + --- + --- + --- + --- + 
    ///                     
    /// </summary>


namespace WordRacer.Domain.Tests.Integration.Fixtures
{
  public class Round4BoardBuilder
  {
    private IGameDictionary _gameDictionary;
    private bool GameDictionaryProvided = false;
    private char _cell1Letter = 'A'; 
    private char _cell2Letter = 'B';
    private char _cell3Letter = 'R';
    private char _cell4Letter = 'A';
    private char _cell5Letter = 'S';
    private char _cell6Letter = 'I';
    private char _cell7Letter = 'G';
    private char _cell8Letter = 'H';
    private char _cell9Letter = 'T';
    private char _cell10Letter = 'R';
    private char _cell11Letter = 'V';
    private char _cell12Letter = 'E';
    private char _cell13Letter = 'E';
    private char _cell14Letter = 'I';
    private char _cell15Letter = 'N';
    private char _cell16Letter = 'E';
    private char _cell17Letter = 'T';
    private char _cell18Letter = 'T';
    private char _cell19Letter = 'S';
    private char _cell20Letter = 'S';
    private char _cell21Letter = 'R';
    private char _cell22Letter = 'M';
    private char _cell23Letter = 'N';
    private char _cell24Letter = 'E';
    private char _cell25Letter = 'E';
    private char _cell26Letter = 'S';
    private char _cell27Letter = 'T';
    private char _cell28Letter = 'V';
    private char _cell29Letter = 'G';
    private char _cell30Letter = 'P';
    private char _cell31Letter = 'D';
    private char _cell32Letter = 'I';

    private GameCellFactory _gameCellFactory;

    public Round4BoardBuilder()
    {
      _gameCellFactory = new GameCellFactory();
      GameDictionaryProvided = false;
    }

    public Board Build()
    {
      if(!GameDictionaryProvided)
      {
        _gameDictionary = BuildBaseDictionary();
      }

      var gameBoardFactory = new BoardFactory();
      var testBoard = gameBoardFactory.CreateGameBoard(_gameDictionary);

      var cellFactory = new GameCellFactory();

      //row 1 
      var cell1 = cellFactory.CreateGameCell();
      cell1.Character = _cell1Letter.ToString();
      var cell2 = cellFactory.CreateGameCell();
      cell2.Character = _cell2Letter.ToString();
      var cell3 = cellFactory.CreateGameCell();
      cell3.Character = _cell3Letter.ToString();
      var cell4 = cellFactory.CreateGameCell();
      cell4.Character = _cell4Letter.ToString();
      //row 2
      var cell5 = cellFactory.CreateGameCell();
      cell5.Character = _cell5Letter.ToString();
      var cell6 = cellFactory.CreateGameCell();
      cell6.Character = _cell6Letter.ToString();
      var cell7 = cellFactory.CreateGameCell();
      cell7.Character = _cell7Letter.ToString();
      var cell8 = cellFactory.CreateGameCell();
      cell8.Character = _cell8Letter.ToString();
      //row 3
      var cell9 = cellFactory.CreateGameCell();
      cell9.Character = _cell9Letter.ToString();
      var cell10 = cellFactory.CreateGameCell();
      cell10.Character = _cell10Letter.ToString();
      var cell11 = cellFactory.CreateGameCell();
      cell11.Character = _cell11Letter.ToString();
      var cell12 = cellFactory.CreateGameCell();
      cell12.Character = _cell12Letter.ToString();
      var cell13 = cellFactory.CreateGameCell();
      cell13.Character = _cell13Letter.ToString();
      var cell14 = cellFactory.CreateGameCell();
      cell14.Character = _cell14Letter.ToString();
      //row 4
      var cell15 = cellFactory.CreateGameCell();
      cell15.Character = _cell15Letter.ToString();
      var cell16 = cellFactory.CreateGameCell();
      cell16.Character = _cell16Letter.ToString();
      var cell17 = cellFactory.CreateGameCell();
      cell17.Character = _cell17Letter.ToString();
      var cell18 = cellFactory.CreateGameCell();
      cell18.Character = _cell18Letter.ToString();
      var cell19 = cellFactory.CreateGameCell();
      cell19.Character = _cell19Letter.ToString();
      var cell20 = cellFactory.CreateGameCell();
      cell20.Character = _cell20Letter.ToString();
      //row 5
      var cell21 = cellFactory.CreateGameCell();
      cell21.Character = _cell21Letter.ToString();
      var cell22 = cellFactory.CreateGameCell();
      cell22.Character = _cell22Letter.ToString();
      var cell23 = cellFactory.CreateGameCell();
      cell23.Character = _cell23Letter.ToString();
      var cell24 = cellFactory.CreateGameCell();
      cell24.Character = _cell24Letter.ToString();
      //row 6
      var cell25 = cellFactory.CreateGameCell();
      cell25.Character = _cell25Letter.ToString();
      var cell26 = cellFactory.CreateGameCell();
      cell26.Character = _cell26Letter.ToString();
      var cell27 = cellFactory.CreateGameCell();
      cell27.Character = _cell27Letter.ToString();
      var cell28 = cellFactory.CreateGameCell();
      cell28.Character = _cell28Letter.ToString();
      var cell29 = cellFactory.CreateGameCell();
      cell29.Character = _cell29Letter.ToString();
      var cell30 = cellFactory.CreateGameCell();
      cell30.Character = _cell30Letter.ToString();
      var cell31 = cellFactory.CreateGameCell();
      cell31.Character = _cell31Letter.ToString();
      var cell32 = cellFactory.CreateGameCell();
      cell32.Character = _cell32Letter.ToString();


      //add cells to board
      testBoard.AddGameCell(cell1);
      testBoard.AddGameCell(cell2);
      testBoard.AddGameCell(cell3);
      testBoard.AddGameCell(cell4);
      testBoard.AddGameCell(cell5);
      testBoard.AddGameCell(cell6);
      testBoard.AddGameCell(cell7);
      testBoard.AddGameCell(cell8);
      testBoard.AddGameCell(cell9);
      testBoard.AddGameCell(cell10);
      testBoard.AddGameCell(cell11);
      testBoard.AddGameCell(cell12);
      testBoard.AddGameCell(cell13);
      testBoard.AddGameCell(cell14);
      testBoard.AddGameCell(cell15);
      testBoard.AddGameCell(cell16);
      testBoard.AddGameCell(cell17);
      testBoard.AddGameCell(cell18);
      testBoard.AddGameCell(cell19);
      testBoard.AddGameCell(cell20);
      testBoard.AddGameCell(cell21);
      testBoard.AddGameCell(cell22);
      testBoard.AddGameCell(cell23);
      testBoard.AddGameCell(cell24);
      testBoard.AddGameCell(cell25);
      testBoard.AddGameCell(cell26);
      testBoard.AddGameCell(cell27);
      testBoard.AddGameCell(cell28);
      testBoard.AddGameCell(cell29);
      testBoard.AddGameCell(cell30);
      testBoard.AddGameCell(cell31);
      testBoard.AddGameCell(cell32);

      //now connect the cells to each other
      //row 1
      testBoard.ConnectTwoCells(cell1, cell2);
      testBoard.ConnectTwoCells(cell1, cell7);
      testBoard.ConnectTwoCells(cell1, cell8);

      testBoard.ConnectTwoCells(cell2, cell3);
      testBoard.ConnectTwoCells(cell2, cell7);
      testBoard.ConnectTwoCells(cell2, cell8);
      testBoard.ConnectTwoCells(cell2, cell9);

      testBoard.ConnectTwoCells(cell3, cell4);
      testBoard.ConnectTwoCells(cell3, cell8);
      testBoard.ConnectTwoCells(cell3, cell9);
      testBoard.ConnectTwoCells(cell3, cell10);

      testBoard.ConnectTwoCells(cell4, cell5);
      testBoard.ConnectTwoCells(cell4, cell9);
      testBoard.ConnectTwoCells(cell4, cell10);
      testBoard.ConnectTwoCells(cell4, cell11);

      testBoard.ConnectTwoCells(cell5, cell6);
      testBoard.ConnectTwoCells(cell5, cell10);
      testBoard.ConnectTwoCells(cell5, cell11);
      testBoard.ConnectTwoCells(cell5, cell12);

      testBoard.ConnectTwoCells(cell6, cell11);
      testBoard.ConnectTwoCells(cell6, cell12);
      //row 2
      testBoard.ConnectTwoCells(cell7, cell8);
      testBoard.ConnectTwoCells(cell7, cell13);
      testBoard.ConnectTwoCells(cell7, cell14);

      testBoard.ConnectTwoCells(cell8, cell9);
      testBoard.ConnectTwoCells(cell8, cell13);
      testBoard.ConnectTwoCells(cell8, cell14);

      testBoard.ConnectTwoCells(cell9, cell10);
      testBoard.ConnectTwoCells(cell9, cell14);

      testBoard.ConnectTwoCells(cell10, cell11);
      testBoard.ConnectTwoCells(cell10, cell15);

      testBoard.ConnectTwoCells(cell11, cell12);
      testBoard.ConnectTwoCells(cell11, cell15);
      testBoard.ConnectTwoCells(cell11, cell16);

      testBoard.ConnectTwoCells(cell12, cell15);
      testBoard.ConnectTwoCells(cell12, cell16);
      //ROW 3
      testBoard.ConnectTwoCells(cell13, cell14);
      testBoard.ConnectTwoCells(cell13, cell17);
      testBoard.ConnectTwoCells(cell13, cell18);

      testBoard.ConnectTwoCells(cell14, cell17);
      testBoard.ConnectTwoCells(cell14, cell18);

      testBoard.ConnectTwoCells(cell15, cell16);
      testBoard.ConnectTwoCells(cell15, cell19);
      testBoard.ConnectTwoCells(cell15, cell20);

      testBoard.ConnectTwoCells(cell16, cell19);
      testBoard.ConnectTwoCells(cell16, cell20);
      //row 4
      testBoard.ConnectTwoCells(cell17, cell18);
      testBoard.ConnectTwoCells(cell17, cell21);
      testBoard.ConnectTwoCells(cell17, cell22);

      testBoard.ConnectTwoCells(cell18, cell21);
      testBoard.ConnectTwoCells(cell18, cell22);
      testBoard.ConnectTwoCells(cell18, cell23);

      testBoard.ConnectTwoCells(cell19, cell20);
      testBoard.ConnectTwoCells(cell19, cell24);
      testBoard.ConnectTwoCells(cell19, cell25);
      testBoard.ConnectTwoCells(cell19, cell26);

      testBoard.ConnectTwoCells(cell20, cell25);
      testBoard.ConnectTwoCells(cell20, cell26);

      //row 5
      testBoard.ConnectTwoCells(cell21, cell22);
      testBoard.ConnectTwoCells(cell21, cell27);
      testBoard.ConnectTwoCells(cell21, cell28);

      testBoard.ConnectTwoCells(cell22, cell23);
      testBoard.ConnectTwoCells(cell22, cell27);
      testBoard.ConnectTwoCells(cell22, cell28);
      testBoard.ConnectTwoCells(cell22, cell29);

      testBoard.ConnectTwoCells(cell23, cell24);      
      testBoard.ConnectTwoCells(cell23, cell28);      
      testBoard.ConnectTwoCells(cell23, cell29);      
      testBoard.ConnectTwoCells(cell23, cell30);

      testBoard.ConnectTwoCells(cell24, cell25);
      testBoard.ConnectTwoCells(cell24, cell29);
      testBoard.ConnectTwoCells(cell24, cell30);
      testBoard.ConnectTwoCells(cell24, cell31);

      testBoard.ConnectTwoCells(cell25, cell26);
      testBoard.ConnectTwoCells(cell25, cell30);
      testBoard.ConnectTwoCells(cell25, cell31);
      testBoard.ConnectTwoCells(cell25, cell32);

      testBoard.ConnectTwoCells(cell25, cell31);
      testBoard.ConnectTwoCells(cell25, cell32);

      //row 6
      testBoard.ConnectTwoCells(cell27, cell28);

      testBoard.ConnectTwoCells(cell28, cell29);

      testBoard.ConnectTwoCells(cell29, cell30);

      testBoard.ConnectTwoCells(cell30, cell31);

      testBoard.ConnectTwoCells(cell31, cell32);      

      return testBoard;
    }

    private GameDictionary BuildBaseDictionary()
    {
      var dictionaryFactory = new DictionaryFactory();
      var baseDictionary = dictionaryFactory.CreateGameDictionary();
      baseDictionary.AddWord("ESS");
      baseDictionary.AddWord("ORT");
      baseDictionary.AddWord("BEE");
      baseDictionary.AddWord("GIT");
      baseDictionary.AddWord("NOG");
      baseDictionary.AddWord("SEAR");
      baseDictionary.AddWord("TREE");
      baseDictionary.AddWord("KIT");
      baseDictionary.AddWord("LOO");
      baseDictionary.AddWord("NOB");
      baseDictionary.AddWord("BOT");
      baseDictionary.AddWord("DREG");
      baseDictionary.AddWord("AMIDS");
      baseDictionary.AddWord("UNARY");
      baseDictionary.AddWord("LOUTED");
      baseDictionary.AddWord("LESSONS");
      baseDictionary.AddWord("LESSON");
      baseDictionary.AddWord("CELS");
      baseDictionary.AddWord("NICHED");
      baseDictionary.AddWord("TOE");
      baseDictionary.AddWord("DUKED");
      baseDictionary.AddWord("INSIST");
      baseDictionary.AddWord("YES");
      baseDictionary.AddWord("SON");
      baseDictionary.AddWord("NOT");
      baseDictionary.AddWord("DEN");
      baseDictionary.AddWord("DIE");
      baseDictionary.AddWord("THE");
      baseDictionary.AddWord("ART");
      baseDictionary.AddWord("SEE");
      baseDictionary.AddWord("SIEVE");
      baseDictionary.AddWord("SEVEN");
      baseDictionary.AddWord("SAVE");
      baseDictionary.AddWord("SAVES");
      baseDictionary.AddWord("BRAVE");
      baseDictionary.AddWord("RAVEN");
      baseDictionary.AddWord("ENVIES");
      baseDictionary.AddWord("DISSENT");
      baseDictionary.AddWord("BRAVENESS");
      baseDictionary.AddWord("ABRASIVENESS");
      return baseDictionary;
    }

    private GameCell BuildGameCell(char letter)
    {
      var gameCell = _gameCellFactory.CreateGameCell();
      gameCell.Character = letter.ToString().ToUpper();
      return gameCell;
    }

    public Round4BoardBuilder WithDictionary(IGameDictionary gameDictionary)
    {
      _gameDictionary = gameDictionary;
      GameDictionaryProvided = true;
      return this;
    }

    public Round4BoardBuilder WithCell1Character(char letter)
    {
      _cell1Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell2Character(char letter)
    {
      _cell2Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell3Character(char letter)
    {
      _cell3Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell4Character(char letter)
    {
      _cell4Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell5Character(char letter)
    {
      _cell5Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell6Character(char letter)
    {
      _cell6Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell7Character(char letter)
    {
      _cell7Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell8Character(char letter)
    {
      _cell8Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell9Character(char letter)
    {
      _cell9Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell10Character(char letter)
    {
      _cell10Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell11Character(char letter)
    {
      _cell11Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell12Character(char letter)
    {
      _cell12Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell13Character(char letter)
    {
      _cell13Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell14Character(char letter)
    {
      _cell14Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell15Character(char letter)
    {
      _cell15Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell16Character(char letter)
    {
      _cell16Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell17Character(char letter)
    {
      _cell17Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell18Character(char letter)
    {
      _cell18Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell19Character(char letter)
    {
      _cell19Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell20Character(char letter)
    {
      _cell20Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell21Character(char letter)
    {
      _cell21Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell22Character(char letter)
    {
      _cell22Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell23Character(char letter)
    {
      _cell23Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell24Character(char letter)
    {
      _cell24Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell25Character(char letter)
    {
      _cell25Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell26Character(char letter)
    {
      _cell26Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell27Character(char letter)
    {
      _cell27Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell28Character(char letter)
    {
      _cell28Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell29Character(char letter)
    {
      _cell29Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell30Character(char letter)
    {
      _cell30Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell31Character(char letter)
    {
      _cell31Letter = letter;
      return this;
    }

    public Round4BoardBuilder WithCell32Character(char letter)
    {
      _cell32Letter = letter;
      return this;
    }
  }
}
